// my-fresh-blog/utils/auth.ts
import { getCookies, setCookie, deleteCookie, Cookie } from "$std/http/cookie.ts";
import { FreshContext } from "$fresh/server.ts";
import { getDbClient } from "./db.ts";
import * as bcrypt from "https://deno.land/x/bcrypt@v0.4.1/mod.ts";

const SESSION_COOKIE_NAME = "admin_session_token_v3";
const SECRET_KEY = Deno.env.get("SESSION_SECRET_KEY") || "my-fresh-blog-super-secret-and-long-key-!@#$%^&*()";

async function signData(data: string): Promise<string> {
  const key = await crypto.subtle.importKey("raw",new TextEncoder().encode(SECRET_KEY),{ name: "HMAC", hash: "SHA-256" },false,["sign"]);
  const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(data));
  return Array.from(new Uint8Array(signature)).map(b => b.toString(16).padStart(2, '0')).join('');
}

async function verifySignedData(data: string, signatureToVerify: string): Promise<boolean> {
  try {
    const expectedSignature = await signData(data);
    return expectedSignature === signatureToVerify;
  } catch (e) {
    console.error("Error during signature verification:", e);
    return false;
  }
}

export async function setAdminSessionCookie(
  respHeaders: Headers, 
  userId: number, 
  username: string, 
  displayName: string,
  avatarUrl: string | null
): Promise<void> {
  console.log("设置管理员会话cookie...");
  const sessionData = JSON.stringify({
    userId,
    username,
    displayName,
    avatarUrl,
    role: 'admin',
    timestamp: Date.now()
  });
  
  console.log("会话数据:", sessionData);
  const signature = await signData(sessionData);
  const encodedSessionData = encodeURIComponent(sessionData);

  const cookie: Cookie = {
    name: SESSION_COOKIE_NAME,
    value: `${encodedSessionData}.${signature}`,
    path: "/", 
    httpOnly: true, 
    sameSite: "Lax",
    // secure: true, // IMPORTANT: Uncomment and ensure HTTPS in production
    maxAge: 60 * 60 * 24 * 7, // 7 days
  };
  
  console.log("设置cookie:", {
    name: SESSION_COOKIE_NAME,
    valuePart: `${encodedSessionData.substring(0, 20)}...`,
    path: "/",
    httpOnly: true,
    maxAge: "7 days"
  });
  
  setCookie(respHeaders, cookie);
  console.log("Cookie已设置");
}

export function deleteAdminSessionCookie(respHeaders: Headers): void {
  deleteCookie(respHeaders, SESSION_COOKIE_NAME, { path: "/", httpOnly: true, sameSite: "Lax" /*, secure: true */ });
}

export interface UserSession {
  userId: number;
  username: string;
  displayName: string;
  avatarUrl: string | null;
  role: string;
  timestamp: number;
}

export async function checkIsAdmin(req: Request, ctx?: FreshContext): Promise<boolean> {
  console.log("检查是否是管理员...");
  const cookies = getCookies(req.headers);
  const sessionCookieValue = cookies[SESSION_COOKIE_NAME];
  console.log("会话cookie是否存在:", !!sessionCookieValue);
  let isAdminAuthenticated = false;
  let userData: UserSession | null = null;

  if (sessionCookieValue) {
    try {
      console.log("尝试解析会话cookie");
      const [encodedSessionDataStr, signature] = sessionCookieValue.split('.');
      
      if (encodedSessionDataStr && signature) {
        console.log("会话数据和签名都存在");
        const sessionDataStr = decodeURIComponent(encodedSessionDataStr);
        const isSignatureValid = await verifySignedData(sessionDataStr, signature);
        console.log("签名验证结果:", isSignatureValid);
        
        if (isSignatureValid) {
          userData = JSON.parse(sessionDataStr) as UserSession;
          console.log("解析的用户数据:", userData ? {
            userId: userData.userId,
            username: userData.username,
            role: userData.role,
            hasTimestamp: !!userData.timestamp
          } : null);
          
          // 验证用户会话数据
          if (userData && userData.role === 'admin' && userData.userId && userData.username) {
            isAdminAuthenticated = true;
            console.log("管理员验证成功");
            
            // 如果 session 超过 4 小时，可以考虑刷新 session
            if (Date.now() - userData.timestamp > 4 * 60 * 60 * 1000) {
              console.log("会话时间超过4小时");
              // 刷新逻辑可以在这里添加
            }
          } else {
            console.log("用户数据验证失败");
          }
        }
      } else {
        console.log("会话数据格式不正确");
      }
    } catch (error) {
      console.error("会话解析错误:", error);
    }
  } else {
    console.log("未找到会话cookie");
  }

  if (ctx?.state) {
    ctx.state.isAdmin = isAdminAuthenticated;
    if (userData) {
      ctx.state.adminUsername = userData.username;
      ctx.state.adminNickname = userData.displayName;
      ctx.state.adminUserId = userData.userId;
      ctx.state.adminAvatarUrl = userData.avatarUrl;
      console.log("设置了管理员状态:", ctx.state.adminNickname);
    }
  }
  
  console.log("最终管理员验证结果:", isAdminAuthenticated);
  return isAdminAuthenticated;
}

export async function verifyAdminCredentials(username?: string | null, password?: string | null): Promise<{ 
  success: boolean; 
  userId?: number; 
  username?: string; 
  displayName?: string;
  avatarUrl?: string | null;
  errorType?: 'username_not_found' | 'incorrect_password' | 'empty_fields' | 'db_error';
}> {
  console.log("开始验证管理员凭证，用户名:", username);
  if (!username || !password) {
    console.log("用户名或密码为空");
    return { success: false, errorType: 'empty_fields' };
  }
  
  const client = await getDbClient();
  try {
    console.log("查询数据库中的管理员账号:", username);
    const results = await client.query(
      "SELECT id, username, password_hash, display_name, role, avatar_url FROM users WHERE username = ? AND role = 'admin'",
      [username]
    );
    
    console.log("查询结果数量:", results.length);
    if (results.length === 0) {
      console.log("未找到用户名对应的管理员账号");
      return { success: false, errorType: 'username_not_found' };
    }
    
    const user = results[0] as { 
      id: number; 
      username: string; 
      password_hash: string; 
      display_name: string; 
      role: string;
      avatar_url: string | null;
    };
    
    console.log("尝试比较密码，数据库哈希值:", user.password_hash.substring(0, 10) + "...");
    const passwordMatch = await bcrypt.compare(password, user.password_hash);
    console.log("密码匹配结果:", passwordMatch);
    
    if (!passwordMatch) {
      console.log("密码不匹配");
      return { success: false, errorType: 'incorrect_password' };
    }
    
    console.log("验证成功");
    return { 
      success: true, 
      userId: user.id, 
      username: user.username, 
      displayName: user.display_name,
      avatarUrl: user.avatar_url
    };
  } catch (error) {
    console.error("验证过程中发生数据库错误:", error);
    return { success: false, errorType: 'db_error' };
  } finally {
    await client.close();
  }
}